
#include "commom.h"


/**
 * @brief 填充可用串口列表到 QComboBox 中
 *
 * 该函数会扫描当前系统中所有可用的串口，并将串口名称和描述信息
 * 添加到指定的 QComboBox 控件中，便于用户选择串口。每一项的显示格式为：
 *     COM3 (USB Serial Device)
 *
 * @param comboBox 指向目标 QComboBox 的指针
 */
void findSerialPorts(QComboBox *comboBox)
{
    comboBox->clear();  // 先清空原有项

    const auto ports = QSerialPortInfo::availablePorts();
    for (const QSerialPortInfo &info : ports) {
        QString portName = info.portName();  // 如 COM3 或 /dev/ttyUSB0
        QString description = info.description();  // 如 "USB Serial Device"

        // 组合显示项内容：端口名称 + 描述
        QString displayText = QString("%1").arg(portName);
        comboBox->addItem(portName, portName);  // 设置显示和用户数据
    }

    // 如果找到串口，则默认选中第一个
    if (!ports.isEmpty()) {
        comboBox->setCurrentIndex(0);
    }
}



QCustomPlot* createCustomPlotWidget(QWidget *parent, const CustomPlotOptions& options )
{
    QCustomPlot *customPlot = new QCustomPlot(parent);

    if (parent->layout()) {
        parent->layout()->addWidget(customPlot);
    } else {
        customPlot->setGeometry(parent->rect());
    }

    // 设置鼠标交互，组合enableZoom和enableDrag
    QCP::Interactions interactions = QCP::iSelectItems; // 保留选中功能，方便后续扩展
    if (options.enableZoom) interactions |= QCP::iRangeZoom;
    if (options.enableDrag) interactions |= QCP::iRangeDrag;
    customPlot->setInteractions(interactions);

    // 添加一条空白曲线，方便后续设置数据
    customPlot->addGraph();

    // 坐标轴标签
    customPlot->xAxis->setLabel(options.xAxisLabel);
    customPlot->yAxis->setLabel(options.yAxisLabel);

    // 网格显示控制
    customPlot->xAxis->grid()->setVisible(options.showGrid);
    customPlot->yAxis->grid()->setVisible(options.showGrid);

    return customPlot;
}

/**
 * @brief 创建并打开一个串口
 * @param portName    串口名，如 "COM3" 或 "/dev/ttyUSB0"
 * @param baudRate    波特率，默认 115200
 * @param dataBits    数据位，默认 8
 * @param stopBits    停止位，默认 1
 * @param parity      校验位，默认无
 * @return 成功则返回 QSerialPort*，失败返回 nullptr
 */
QSerialPort* createSerialPort(const QString &portName,
                              qint32 baudRate ,
                              QSerialPort::DataBits dataBits,
                              QSerialPort::StopBits stopBits ,
                              QSerialPort::Parity parity)
{
    QSerialPort *serial = new QSerialPort;

    serial->setPortName(portName);
    serial->setBaudRate(baudRate);
    serial->setDataBits(dataBits);
    serial->setStopBits(stopBits);
    serial->setParity(parity);
    serial->setFlowControl(QSerialPort::NoFlowControl);

    if (!serial->open(QIODevice::ReadWrite)) {
        delete serial;
        return nullptr;
    }

    return serial;
}




// 安全访问函数：返回指针，可读写
template<typename T>
T* qvecSafeAt(QVector<T>& vec, int index) {
    if (index >= 0 && index < vec.size()) {
        return &vec[index];   // 返回元素地址，可通过 *ptr 修改
    } else {
        qWarning() << "qvecSafeAt: index" << index << "out of range. Current size:" << vec.size();
        return nullptr;       // 越界返回 nullptr
    }
}

// 安全修改函数：直接修改元素
template<typename T>
bool qvecSafeSet(QVector<T>& vec, int index, const T& value) {
    if (index >= 0 && index < vec.size()) {
        vec[index] = value;
        return true;
    } else {
        qWarning() << "qvecSafeSet: index" << index << "out of range. Current size:" << vec.size();
        return false;
    }
}


template<typename T>
T* qlistSafeAt(QList<T>& list, int index) {
    if (index >= 0 && index < list.size()) {
        return &list[index];   // 返回元素地址
    } else {
        qWarning() << "qlistSafeAt: index" << index << "out of range. Current size:" << list.size();
        return nullptr;       // 越界返回 nullptr
    }
}

/**
 * @brief 安全修改 QList 元素
 * @param list 目标 QList
 * @param index 要修改的索引
 * @param value 新值
 * @return 修改成功返回 true，索引越界返回 false
 */
template<typename T>
bool qlistSafeSet(QList<T>& list, int index, const T& value) {
    if (index >= 0 && index < list.size()) {
        list[index] = value;
        return true;
    } else {
        qWarning() << "qlistSafeSet: index" << index << "out of range. Current size:" << list.size();
        return false;
    }
}
//支持多INI文件的全局函数
QSettings *GlobalIni(const QString path)
{
    // 静态映射表（路径 → QSettings指针）
    static QMap<QString, QSettings*> iniMap;

    QString fullPath;

    // 如果是绝对路径就直接用，否则放在程序目录下
    if (QDir(path).isAbsolute()) {
        fullPath = path;
    } else {
        fullPath = QCoreApplication::applicationDirPath() + "/" + path;
    }

    // 查找是否已有实例
    if (iniMap.contains(fullPath)) {
        return iniMap.value(fullPath);
    }

    // 新建一个QSettings对象并加入映射表
    QSettings *newIni = new QSettings(fullPath, QSettings::IniFormat);
    newIni->setIniCodec("UTF-8");

    iniMap.insert(fullPath, newIni);
    qDebug() << "GlobalIni created:" << fullPath;

    return newIni;
}



